package com.yox.rpc.transport.socket.server;

import com.yox.rpc.factory.ThreadPoolFactory;
import com.yox.rpc.handler.RequestHandler;
import com.yox.rpc.hook.ShutdownHook;
import com.yox.rpc.provider.ServiceProviderImpl;
import com.yox.rpc.registry.NacosServiceRegistry;
import com.yox.rpc.serializer.CommonSerializer;
import com.yox.rpc.transport.AbstractRpcServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;

/**
 * 服务端
 * 使用一个 serverSocket 监听端口，循环接收链接请求
 * 如果收到一个链接请求就创建一个线程去处理，所以这里创建一个线程池
 * @serviceRegistry 服务注册表
 */
public class SocketServer extends AbstractRpcServer {

    private static final Logger logger = LoggerFactory.getLogger(SocketServer.class);

    private final ExecutorService threadPool;
    private final CommonSerializer serializer;
    private RequestHandler requestHandler = new RequestHandler();

    public SocketServer(String host, int port){
        this(host, port, DEFAULT_SERIALIZER);
    }

    public SocketServer(String host, int port, Integer serializerID) {
        this.host = host;
        this.port = port;
        this.threadPool = ThreadPoolFactory.createDefaultThreadPool("socket-rpc-server");
        this.serviceRegistry = new NacosServiceRegistry();
        this.serviceProvider = new ServiceProviderImpl();
        this.serializer = CommonSerializer.getByCode(serializerID);
        scanServices();
    }

    // 启动服务
    @Override
    public void start() {

        try (ServerSocket serverSocket = new ServerSocket()) {
            serverSocket.bind(new InetSocketAddress(host, port));
            logger.info("服务器正在启动...");
            // 添加钩子，服务端关闭时会注销服务
            ShutdownHook.getShutdownHook().addClearAllHook();
            Socket socket;
            logger.info("服务器启动完成，等待客户端连接...");
            // 循环等待 客户端连接
            while ((socket = serverSocket.accept()) != null) {
                logger.info("客户端连接成功！IP为：" + socket.getInetAddress() + ":" + socket.getPort());
                threadPool.execute(new SocketRequestHandlerThread(socket, requestHandler, serializer));
            }
            threadPool.shutdown();
        } catch (IOException e) {
            logger.error("服务器启动时发生错误", e);
        }
    }
}
